# ============================================================================
# Copyright (c) 2011-2012 University of Pennsylvania
# Copyright (c) 2013-2014 Andreas Schuh
# All rights reserved.
#
# See COPYING file for license information or visit
# http://opensource.andreasschuh.com/cmake-basis/download.html#license
# ============================================================================

##############################################################################
# @file  cmake_uninstall.cmake
# @brief Uninstallation script based on install_manifest*.txt files.
#
# @ingroup CMakeTools
##############################################################################

cmake_minimum_required (VERSION 2.8.4)

# ----------------------------------------------------------------------------
# set the install prefix
if (NOT DEFINED CMAKE_INSTALL_PREFIX)
  set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
endif ()

# ----------------------------------------------------------------------------
# set the install configuration name
if (NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
  if (BUILD_TYPE)
    string (REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
  else ()
    set (CMAKE_INSTALL_CONFIG_NAME "@CMAKE_BUILD_TYPE@")
  endif ()
  message (STATUS "Uninstall configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif ()

# ----------------------------------------------------------------------------
# set the component getting uninstalled
if (NOT CMAKE_INSTALL_COMPONENT)
  if (COMPONENT)
    message (STATUS "Uninstall component: \"${COMPONENT}\"")
    set (CMAKE_INSTALL_COMPONENT "${COMPONENT}")
  else ()
    set (CMAKE_INSTALL_COMPONENT)
  endif ()
endif ()

# ----------------------------------------------------------------------------
# read manifest file
if (MANIFEST_FILE)
  if (NOT EXISTS "${MANIFEST_FILE}")
    message (FATAL_ERROR "Manifest file ${MANIFEST_FILE} does not exist!")
  endif ()
else ()
  if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@InstallManifest.txt")
    # install manifest written to installation tree
    set (MANIFEST_FILE "${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@InstallManifest.txt")
  elseif (CMAKE_INSTALL_COMPONENT)
    set (MANIFEST_FILE "${CMAKE_CURRENT_LIST_DIR}/install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
  else ()
    set (MANIFEST_FILE "${CMAKE_CURRENT_LIST_DIR}/install_manifest.txt")
  endif ()
endif ()

if (NOT EXISTS "${MANIFEST_FILE}")
  message ("No manifest file found.")
  return ()
endif ()

file (READ "${MANIFEST_FILE}" MANIFEST)
string (REGEX REPLACE "\n" ";" MANIFEST "${MANIFEST}")
list (REVERSE MANIFEST)

# ----------------------------------------------------------------------------
# remove package from CMake package registry
set (REGISTERED "@BASIS_REGISTER@")
if (WIN32 AND REGISTERED)
  set (PKGUID "@TOPLEVEL_PROJECT_PACKAGE_UID@")
  execute_process (
    COMMAND reg delete "HKCU\\Software\\Kitware\\CMake\\Packages\\@PROJECT_PACKAGE_CONFIG_PREFIX@" /v "${PKGUID}" /f
    RESULT_VARIABLE RT
    ERROR_VARIABLE ERR
  )
  if (RT EQUAL 0)
    message (STATUS "Deregister:   Removed HKCU\\Software\\Kitware\\CMake\\Packages\\@PROJECT_PACKAGE_CONFIG_PREFIX@\\${PKGUID}")
  else ()
    string (STRIP "${ERR}" ERR)
    message (STATUS "Deregister:   Failed to remove package from registry: ${ERR}")
  endif ()
endif ()

# ----------------------------------------------------------------------------
# remove installed files
foreach (F ${MANIFEST}) # skip empty entries, i.e., blank lines
  set (F "$ENV{DESTDIR}${F}") # support change of root
  if (EXISTS "${F}")
    set (FILE_IN_USE FALSE)
    if (NOT FILE_IN_USE)
      message (STATUS "Uninstalling: ${F}")
      execute_process (COMMAND "${CMAKE_COMMAND}" -E remove -f "${F}" RESULT_VARIABLE RT)
      if (NOT RT EQUAL 0)
        set (OK FALSE)
        message (STATUS "Failed to uninstall ${F}")
      endif ()
      # remove .pyc files of .py files
      if (F MATCHES "\\.py$" AND EXISTS "${F}c")
        message (STATUS "Uninstalling: ${F}c")
        execute_process (COMMAND "${CMAKE_COMMAND}" -E remove -f "${F}c" RESULT_VARIABLE RT)
        if (NOT RT EQUAL 0)
          message (STATUS "Failed to uninstall ${F}c")
        endif ()
      endif ()
    else ()
      message (STATUS "File-in-use:  ${F}")
    endif ()
  else ()
    message (STATUS "Non-existent: ${F}")
  endif ()
endforeach ()

if (EXISTS "${MANIFEST_FILE}")
  execute_process (COMMAND "${CMAKE_COMMAND}" -E remove -f "${MANIFEST_FILE}")
endif ()

# ----------------------------------------------------------------------------
# remove empty directories
list (APPEND EXCLUDE_DIRS
  "/"
  "/usr"
  "/usr/local"
  "/opt"
  "/opt/local"
  "$ENV{HOME}"
  "$ENV{HOME}/local"
  # these should anyway never be used as installation prefix without subdirectory
  "/bin"
  "/boot"
  "/dev"
  "/etc"
  "/home"
  "/lib"
  "/lib32"
  "/lib64"
  "/media"
  "/mnt"
  "/root"
  "/proc"
  "/sys"
  "/var"
  "/tmp"
  "/lost+found"
  "/cdrom"
)

if (WIN32)
  get_filename_component (PROGRAM_FILES_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion;ProgramFilesDir]" ABSOLUTE)
  if (NOT PROGRAM_FILES_DIR OR PROGRAM_FILES_DIR MATCHES "/registry")
    set (PROGRAM_FILES_DIR "C:/Program Files")
  endif ()
  list (APPEND EXCLUDE_DIRS "${PROGRAM_FILES_DIR}")
  string (REPLACE "/" "\\" PROGRAM_FILES_DIR "${PROGRAM_FILES_DIR}")
  list (APPEND EXCLUDE_DIRS "${PROGRAM_FILES_DIR}")
endif ()

# stop removing directories at root installation directory
# the subdirectory will be still removed if it is not in the
# list of excluded system directories
get_filename_component (D "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}" PATH)
list (APPEND EXCLUDE_DIRS "${D}")

string (REPLACE "." "\\." CMAKE_INSTALL_PREFIX_RE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}")
string (REPLACE "." "\\." CMAKE_REGISTRY_PREFIX_RE "$ENV{HOME}/.cmake")

foreach (F ${MANIFEST}) # skip empty entries, i.e., blank lines
  # remove directories only if file was installed inside the installation root
  # or the CMake package registration on Unix
  if (F MATCHES "^${CMAKE_INSTALL_PREFIX_RE}" OR
        (UNIX AND F MATCHES "^${CMAKE_REGISTRY_PREFIX_RE}"))
    get_filename_component (D "$ENV{DESTDIR}${F}" PATH)
    while (D)
      # skip directory if we removed it already
      if (NOT EXISTS "${D}" OR NOT IS_DIRECTORY "${D}")
        if ("${D}" STREQUAL "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}")
          return () # we are done, the installation root has been removed
        endif ()
        break ()
      endif ()
      # skip directory if it is in list of excluded directories
      list (FIND EXCLUDE_DIRS "${D}" IDX)
      if (NOT IDX EQUAL -1)
        break ()
      endif ()
      # glob files in directory to make sure it is empty
      file (GLOB FILES "${D}/*")
      if (NOT FILES)
        # remove directory
        message (STATUS "Uninstalling: ${D}")
        execute_process (COMMAND "${CMAKE_COMMAND}" -E remove_directory "${D}" RESULT_VARIABLE RT)
        if (NOT RT EQUAL 0)
          set (OK FALSE)
          message (STATUS "Failed to remove ${D}")
        endif ()
      endif ()
      if ("${D}" STREQUAL "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}")
        # we reached the root installation direcory
        break ()
      endif ()
      # procede with parent directory
      get_filename_component (D "${D}" PATH)
    endwhile ()
  endif ()
endforeach ()
